package main

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"

	// "path/filepath"

	"github.com/gin-gonic/gin"
	"github.com/masterzen/winrm"
)

type UserToVm struct {
	Data           []string `json:"data"`
	Length         uint8    `json:"length"`
	Ids            []int    `json:"ids"`
	RdpDomain      string   `json:"rdpdomain"`
	RdpGateWay     string   `json:"rdpgateway"`
	RdpGateWayPort string   `json:"rdpgatewayport"`
	Ipv4           []string `json:"ipv4"`
}

type Result struct {
	Data string `json:"data"`
}

type DefaultParameters struct {
	TransportDecorator string
}

type MergeInfo struct {
	Key         string   `json:"key"`
	FileName    string   `json:"fileName"`
	ChunkFiles  []string `json:"chunkFiles"`
	Cecip       string   `json:"cecip"`
	Cecusername string   `json:"cecusername"`
}

type WebRdpInfo struct {
	Status bool   `json:"status"`
	Date   string `json:"data"`
}

func ApiWebLogin() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.ParseForm()
		username := c.PostForm("username")
		password := c.PostForm("password")
		ManagerServer := c.PostForm("manager_server")
		fmt.Println(ManagerServer)
		client := &http.Client{}
		postData := url.Values{}
		postData.Set("username", username)
		postData.Set("password", password)
		resp, err := client.Post(ManagerServer+"/cec_cc/web_rdplogin", "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
		if err != nil {
			fmt.Println(err)
			return
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		//fmt.Println(resp.StatusCode)
		//fmt.Println(string(body))
		//fmt.Println(reflect.TypeOf(string(body)))
		userLoginStruct := userLogin{}
		err = json.Unmarshal(body, &userLoginStruct)
		fmt.Println(err)
		if err != nil {
			fmt.Println(err)
		}
		//fmt.Println(userLoginStruct)
		//fmt.Println(userLoginStruct.Data)
		//fmt.Println(userLoginStruct.Data.Username)
		//c.JSON(200, gin.H{"username": username, "password": password})
		c.JSON(200, userLoginStruct)
	}
}

func ApiGetRdpInfo() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.ParseForm()
		user_uuid := c.PostForm("user_uuid")
		ManagerServer := c.PostForm("manager_server")
		fmt.Println(user_uuid)
		client := &http.Client{}
		postData := url.Values{}
		postData.Set("user_uuid", user_uuid)
		resp, err := client.Post(ManagerServer+"/cec_cc/web_getrdpinfo", "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
		if err != nil {
			fmt.Println(err)
			return
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		//fmt.Println(resp.StatusCode)
		//fmt.Println(string(body))
		//fmt.Println(reflect.TypeOf(string(body)))
		userUuid := UserUuid{}
		err = json.Unmarshal(body, &userUuid)
		fmt.Println(err)
		if err != nil {
			fmt.Println(err)
		}
		c.JSON(200, userUuid)
	}
}

func ApiGetUser2VmInfo() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.ParseForm()
		username := c.PostForm("username")
		ManagerServer := c.PostForm("manager_server")
		fmt.Println(username)
		client := &http.Client{}
		postData := url.Values{}
		postData.Set("username", username)
		resp, err := client.Post(ManagerServer+"/cec_cc/usertovm", "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
		if err != nil {
			fmt.Println(err)
			return
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		//fmt.Println(resp.StatusCode)
		fmt.Println(string(body))
		//fmt.Println(reflect.TypeOf(string(body)))
		userToVm := UserToVm{}
		err = json.Unmarshal(body, &userToVm)
		fmt.Println(err)
		if err != nil {
			fmt.Println(err)
		}
		fmt.Println(userToVm)
		c.JSON(200, userToVm)
	}

}

func ApiUpLoad() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Multipart form
		form, _ := c.MultipartForm()
		files := form.File["upload"]
		result := Result{}
		fmt.Println(form.File)
		fmt.Println(files)
		c.Request.ParseForm()
		cecip := c.PostForm("cecip")
		cecusername := c.PostForm("cecusername")

		for _, file := range files {
			// 打开上传的文件
			src, err := file.Open()
			if err != nil {
				c.String(http.StatusBadRequest, "File open error: %s", err.Error())
				return
			}
			defer src.Close()

			// 创建保存文件
			dst, err := os.Create("./upload/" + file.Filename)
			if err != nil {
				c.String(http.StatusBadRequest, "File create error: %s", err.Error())
				return
			}
			defer dst.Close()

			// 边读边写
			if _, err = io.Copy(dst, src); err != nil {
				result.Data = "test"
				c.String(http.StatusBadRequest, "File save error: %s", err.Error())
				return
			}
			RunPyComd(file.Filename, cecip, cecusername, "upload")
			//RunWinrmComd()
		}

		result.Data = "test"
		c.JSON(http.StatusOK, result)
	}

}

func ApiChunkUpLoad() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Multipart form
		file, _, err := c.Request.FormFile("file")
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": "无法读取上传文件",
			})
			return
		}
		defer file.Close()

		// 获取上传文件的唯一标识
		key := c.PostForm("key")
		// 获取切片哈希值
		hash := c.PostForm("hash")
		cecusername := c.PostForm("cecusername")
		//获取文件大小
		file_sizeStr := c.PostForm("file_size")
		file_size, err := strconv.ParseInt(file_sizeStr, 10, 64)
		// 保存上传的切片到临时目录
		uploadPath := "./temp/" + cecusername + "/" + key
		if err := os.MkdirAll(uploadPath, 0755); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "无法创建上传目录",
			})
			return
		}

		chunkFileName := filepath.Join(uploadPath, hash)
		var out *os.File
		if !PathExists(chunkFileName) {
			out, err = os.Create(chunkFileName)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": "无法创建切片文件",
				})
				return
			}

		} else {
			// 获取文件大小（以字节为单位）
			fileInfo, _ := os.Stat(chunkFileName)
			fileSize := fileInfo.Size()
			if fileSize == file_size {
				c.JSON(http.StatusOK, gin.H{
					"message": "缓存",
				})
				return
			}
			out, err = os.Open(chunkFileName)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": "无法打开切片文件",
				})
				return
			}

		}
		defer out.Close()
		// 获取文件信息

		// 将切片流复制到切片文件
		_, err = io.Copy(out, file)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "无法写入切片文件",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"message": "切片上传成功",
		})
	}

}

func ApiChunkUpLoadmMrge() gin.HandlerFunc {
	return func(c *gin.Context) {
		var mergeInfo MergeInfo
		if err := c.BindJSON(&mergeInfo); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "参数有误",
			})
			return
		}
		// 获取临时目录下的所有切片文件
		uploadPath := "./temp/" + mergeInfo.Cecusername + "/" + mergeInfo.Key
		uploadFilesPath := "./upload/" + mergeInfo.Cecusername
		if err := os.MkdirAll(uploadFilesPath, 0755); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "无法创建上传目录",
			})
			return
		}
		// 创建目标文件并合并切片
		mergeFileName := filepath.Join(uploadFilesPath, mergeInfo.FileName)

		mergeFile, err := os.Create(mergeFileName)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "无法创建合并文件",
			})
			return
		}
		defer mergeFile.Close()
		for _, chunkFile := range mergeInfo.ChunkFiles {
			chunk, err := os.Open(path.Join(uploadPath, chunkFile))
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": "无法打开切片文件",
				})
				return
			}

			_, err = io.Copy(mergeFile, chunk)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": "无法合并切片文件",
				})
				return
			}
			chunk.Close()
		}
		err = os.RemoveAll(uploadPath)
		// RunPyComd(mergeInfo.FileName, mergeInfo.Cecip, mergeInfo.Cecusername)
		c.JSON(http.StatusOK, gin.H{
			"message": "文件合并成功",
			"file":    mergeFileName,
		})
		RunPyComd(mergeInfo.FileName, mergeInfo.Cecip, mergeInfo.Cecusername, "upload")
	}
}

func PathExists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}

func ApiDownLoad() gin.HandlerFunc {
	return func(c *gin.Context) {
		fileName := c.Query("filename")
		cecusername := c.Query("cecusername")
		//var fileName string = "海龙工具绿色v2017.10.28.zip"
		//filepath := "./upload/" + cecusername + "/" + fileName
		// defer os.Remove(filepath)
		defer DownloadEnd(cecusername, fileName)
		c.Header("Content-Type", "application/octet-stream")             //换起浏览器得下载
		c.Header("Content-Disposition", "attachment;filename="+fileName) //设置文件名
		c.File("./upload/" + cecusername + "/" + fileName)
	}
}

func DownloadEnd(cecusername string, fileName string) {
	filepath := "./upload/" + cecusername + "/" + fileName
	os.Remove(filepath)
	// RunPyComd(fileName, "", cecusername, "alc")

}

func ApiDownLoadEnd() gin.HandlerFunc {
	return func(c *gin.Context) {
		fileName := c.Query("filename")
		cecusername := c.Query("cecusername")
		filepath := "./upload/" + cecusername + "/" + fileName
		os.Remove(filepath)
		c.JSON(http.StatusOK, gin.H{
			"message": "临时文件删除成功",
		})
	}
}

func RunWinrmComd() {
	endpoint := winrm.NewEndpoint("10.10.0.193", 5985, false, false, nil, nil, nil, 0)
	params := winrm.DefaultParameters
	params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientNTLM{} }
	client, err := winrm.NewClientWithParameters(endpoint, "cec\\administrator", "cec-2023", params)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(client)
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	commd := "$client=new-object System.Net.WebClient; $client.DownloadFile('http://10.10.0.183:9528/api/download', 'C:\\tr\\DJI_WIN_Driver_Installer.exe')"
	res, err := client.RunWithContextWithInput(ctx, commd, os.Stdout, os.Stderr, os.Stdin)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(res)
}

func RunPyComd(fileName string, cecip string, cecusername string, stauts string) {
	dir, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("Work path is: ", dir)
	fmt.Println(cecip)
	fmt.Println(fileName)
	fmt.Println(cecusername)
	// cmd := exec.Command("python3 python/winrmdownload.py") // 要运行的Linux命令及其参数
	// args := []string{dir + "/python/winrmdownload.py", cecip, fileName, cecusername}
	// cmd := exec.Command("python3", args...)
	// output, err := cmd.Output() // 获取命令输出结果
	// if err != nil {
	// 	fmt.Println(err)
	// 	return
	// }
	// fmt.Println(string(output)) // 打印命令输出结果
	client := &http.Client{}
	postData := url.Values{}
	postData.Set("cecip", cecip)
	postData.Set("fileName", fileName)
	postData.Set("cecusername", cecusername)
	postData.Set("stauts", stauts)
	//打包之前修改
	var url = "http://apppy.mojotv.cn:9530/api/winrmdownload"
	//var url = "http://127.0.0.1:9530/api/winrmdownload"
	resp, err := client.Post(url, "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()

}

func ApiGetRdpWebSite() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.ParseForm()
		ManagerServer := c.PostForm("manager_server")
		username := c.PostForm("username")
		fmt.Println(ManagerServer)
		fmt.Println(username)
		client := &http.Client{}
		postData := url.Values{}
		postData.Set("username", username)
		resp, err := client.Post(ManagerServer+"/cec_cc/get_rdp_web_site", "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
		if err != nil {
			fmt.Println(err)
			return
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		//fmt.Println(resp.StatusCode)
		fmt.Println(string(body))
		//fmt.Println(reflect.TypeOf(string(body)))
		webRdpInfo := WebRdpInfo{}
		err = json.Unmarshal(body, &webRdpInfo)
		fmt.Println(err)
		if err != nil {
			fmt.Println(err)
		}
		fmt.Println(webRdpInfo)
		c.JSON(200, webRdpInfo)
	}
}

func ApiSmsSend() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.ParseForm()
		ManagerServer := c.PostForm("manager_server")
		username := c.PostForm("username")
		code := c.PostForm("code")
		fmt.Println(ManagerServer)
		fmt.Println(username)
		client := &http.Client{}
		postData := url.Values{}
		postData.Set("username", username)
		postData.Set("code", code)
		postData.Set("smsname", "阿里云短信-修改密码验证码")
		resp, err := client.Post(ManagerServer+"/cec_cc/sms_send", "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
		if err != nil {
			fmt.Println(err)
			return
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		//fmt.Println(resp.StatusCode)
		fmt.Println(string(body))
		//fmt.Println(reflect.TypeOf(string(body)))
		//webRdpInfo := WebRdpInfo{}
		//err = json.Unmarshal(body, &webRdpInfo)
		//fmt.Println(err)
		//if err != nil {
		//fmt.Println(err)
		//}
		//fmt.Println(webRdpInfo)
		c.JSON(200, string(body))
	}
}

func ApiSmsChangepw() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.ParseForm()
		ManagerServer := c.PostForm("manager_server")
		username := c.PostForm("username")
		newpassword := c.PostForm("newpassword")
		fmt.Println(ManagerServer)
		fmt.Println(username)
		client := &http.Client{}
		postData := url.Values{}
		postData.Set("username", username)
		postData.Set("newpassword", newpassword)
		resp, err := client.Post(ManagerServer+"/cec_cc/sms_changepw", "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
		if err != nil {
			fmt.Println(err)
			return
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		//fmt.Println(resp.StatusCode)
		fmt.Println(string(body))
		//fmt.Println(reflect.TypeOf(string(body)))
		//webRdpInfo := WebRdpInfo{}
		//err = json.Unmarshal(body, &webRdpInfo)
		//fmt.Println(err)
		//if err != nil {
		//fmt.Println(err)
		//}
		//fmt.Println(webRdpInfo)
		c.JSON(200, string(body))
	}
}

func ApiVminfo() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.ParseForm()
		vmid := c.PostForm("vmid")
		ManagerServer := c.PostForm("manager_server")
		fmt.Println(vmid)
		fmt.Println(ManagerServer)
		client := &http.Client{}
		postData := url.Values{}
		postData.Set("vmid", vmid)
		resp, err := client.Post(ManagerServer+"/cec_cc/vminfo", "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
		if err != nil {
			fmt.Println(err)
			return
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println(resp.StatusCode)
		fmt.Println(string(body))
		//fmt.Println(reflect.TypeOf(string(body)))
		//webRdpInfo := WebRdpInfo{}
		//err = json.Unmarshal(body, &webRdpInfo)
		//fmt.Println(err)
		//if err != nil {
		//fmt.Println(err)
		//}
		//fmt.Println(webRdpInfo)
		c.JSON(200, string(body))
	}
}

func ApiVmstart() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.ParseForm()
		vmid := c.PostForm("vmid")
		ManagerServer := c.PostForm("manager_server")
		fmt.Println(vmid)
		fmt.Println(ManagerServer)
		client := &http.Client{}
		postData := url.Values{}
		postData.Set("vmid", vmid)
		resp, err := client.Post(ManagerServer+"/cec_cc/vmstart", "application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
		if err != nil {
			fmt.Println(err)
			return
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println(resp.StatusCode)
		fmt.Println(string(body))
		//fmt.Println(reflect.TypeOf(string(body)))
		//webRdpInfo := WebRdpInfo{}
		//err = json.Unmarshal(body, &webRdpInfo)
		//fmt.Println(err)
		//if err != nil {
		//fmt.Println(err)
		//}
		//fmt.Println(webRdpInfo)
		c.JSON(200, string(body))
	}
}

func ApiGetServerDelay() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.JSON(200, string("获取延时成功"))
	}
}
